package vendas.business;

import gminet.infra.business.BusinessException;
import gminet.infra.business.BusinessObject;
import gminet.infra.dao.ImageTrasnferObject;
import gminet.infra.db.Transaction;
import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.toolkit.StringToolkit;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import vendas.dao.OrderDAO;
import vendas.dao.OrderFilter;
import vendas.dao.ProductDAO;
import vendas.dto.ActiveStatus;
import vendas.dto.Order;
import vendas.dto.Product;

public class ProductBusiness extends BusinessObject {

    private static List<Product> cacheProductList = null;

    public static Product findByPK(int productId) throws BusinessException, TransactionException {

        Product product = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            product = ProductDAO.findByPK(productId, conn);
            if (product == null) {
                throw new BusinessException("Produto não encontrado.");
            }
        } finally {
            transaction.release();
        }
        return product;
    }

    public static List<Product> findAll() throws TransactionException {

        return findAll(false);
    }

    public static List<Product> findAll(boolean useCache) throws TransactionException {

        List<Product> products = null;
        Transaction transaction = createTransaction();
        try {
            if (useCache) {
                if (cacheProductList == null) {
                    Connection conn = transaction.getConnection();
                    cacheProductList = ProductDAO.findAll(conn);
                }
                products = new ArrayList<Product>(cacheProductList);
            } else {
                Connection conn = transaction.getConnection();
                products = ProductDAO.findAll(conn);
            }
        } finally {
            transaction.release();
        }
        return products;
    }

    public static Product insert(Product product, ImageTrasnferObject imageTO) throws BusinessException,
            TransactionException {

        Product newProduct = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // PRODUCT
            int rangeId = createRangeId(product.getName());
            product.setId(ProductDAO.getNextCodigo(conn, rangeId, rangeId + 1000));
            String fileName = "";
            if (imageTO != null && imageTO.hasData()) {
                fileName = "IMG_" + product.getId() + "." + imageTO.getRealFileExtension();
            }
            product.setImageFileName(fileName);
            product.setActiveStatus(ActiveStatus.ACTIVE);
            ProductDAO.insert(product, conn);
            // IMAGE
            if (imageTO != null && imageTO.hasData()) {
                imageTO.setFileName(fileName);
                File imageFile = new File(imageTO.getCompleteFileName());
                try {
                    imageFile.createNewFile();
                    FileOutputStream fos;
                    fos = new FileOutputStream(imageFile);
                    fos.write(imageTO.getData());
                    fos.flush();
                    fos.close();
                } catch (IOException ioe) {
                    throw new TransactionException(ioe.getLocalizedMessage());
                }
            }
            // COMMIT
            transaction.commit();
            //
            clearCache();
            //
            newProduct = product;
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return newProduct;
    }

    private static int createRangeId(String productName) {

        String strCodigo = "1";
        String caracter1 = productName.substring(0, 1).toUpperCase();
        String caracter2 = productName.substring(1, 2).toUpperCase();
        int valor1 = Math.abs(caracter1.compareTo("A") + 1);
        if (StringToolkit.isDigit(caracter1)) {
            valor1 = 0;
        }
        int valor2 = Math.abs(caracter2.compareTo("A") / 3);
        if (StringToolkit.isDigit(caracter2)) {
            valor2 = 0;
        }
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor1, 99), 2);
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor2, 9), 1);
        strCodigo += "000";
        return Integer.parseInt(strCodigo);
    }

    public static void update(Product product) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            Product auxProduct = ProductDAO.findByPK(product.getId(), conn);
            product.setActiveStatus(auxProduct.getActiveStatus());
            ProductDAO.update(product, conn);
            // COMMIT
            transaction.commit();
            //
            clearCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updateActiveStatus(Product product) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            boolean deleted = false;
            //
            if (product.getActiveStatus().equals(ActiveStatus.INACTIVE)) {
                OrderFilter orderFilter = new OrderFilter();
                orderFilter.setProduct(product);
                List<Order> orders = OrderDAO.findByFilter(orderFilter, conn);
                if (orders.size() == 0) {
                    ProductDAO.delete(product, conn);
                    deleted = true;
                }
            }
            //
            if (!deleted) {
                Product auxProduct = ProductDAO.findByPK(product.getId(), conn);
                product.setName(auxProduct.getName());
                product.setDescription(auxProduct.getDescription());
                product.setImageFileName(auxProduct.getImageFileName());
                ProductDAO.update(product, conn);
            }
            // COMMIT
            transaction.commit();
            //
            clearCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void delete(Product product) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            ProductDAO.delete(product, conn);
            transaction.commit();
            //
            clearCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    private static void clearCache() {

        if (cacheProductList != null) {
            cacheProductList.clear();
        }
        cacheProductList = null;
    }

}
